package com.gdut.sport;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.DotOptions;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.gdut.sport.common.BitmapUtils;
import com.gdut.sport.common.FileUtils;
import com.gdut.sport.db.History;
import com.gdut.sport.db.HistoryDao;

import java.io.File;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;

public class MainAppActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainAppActivity.class.getSimpleName();

    private MapView mMapView;
    private BaiduMap mBaiduMap;

    // 定位相关B
    private boolean mFirstLoc = true;
    private boolean mStart = false;
    // 计算距离
    private DecimalFormat mDecimalFormat = new DecimalFormat("0.0");
    private double sum_distance = 0;
    private final double EARTH_RADIUS = 6378137.0;
    // 计算速度
    private float mCurrentSpeed = 0.0f;
    private float mMaxSpeed = 0.0f;
    private LocationClient mLocationClient;
    private List<LatLng> pointstwo = new ArrayList<>();
    LatLng p1, p2;
    private BDLocationListener mBDLocationListener = new BDLocationListener() {

        @Override
        public void onReceiveLocation(BDLocation bdLocation) {

            if (bdLocation == null || mMapView == null) {
                return;
            }
            Log.e(TAG, "onReceiveLocation");
            MyLocationData locData = new MyLocationData.Builder()
//                    .accuracy(bdLocation.getRadius())
                    .accuracy(0)
                    .direction(100)
                    .latitude(bdLocation.getLatitude())
                    .longitude(bdLocation.getLongitude())
                    .build();
            mBaiduMap.setMyLocationData(locData);

            if (mFirstLoc) {
                Log.e(TAG, "onReceiveLocation:first");
                mFirstLoc = false;
                p1 = p2 = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
//                p1 = p2 = fixOffset(bdLocation.getLatitude(), bdLocation.getLongitude());
                MapStatusUpdate msu = MapStatusUpdateFactory.newLatLngZoom(p2, 20);
                mBaiduMap.animateMapStatus(msu);
            } else {
                if (!mStart) {
                    return;
                }
                LatLng p0 = p2;
                p2 = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
//                p2 = fixOffset(bdLocation.getLatitude(), bdLocation.getLongitude());
                sum_distance = sum_distance + gps2m(p0.latitude, p0.longitude, p2.latitude, p2.longitude);
                MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(p2);
                OverlayOptions options = new DotOptions().center(p2).radius(6).color(0xAAFF0000);
                mBaiduMap.addOverlay(options);
                mBaiduMap.animateMapStatus(msu);
                mDistanceText.setText(mDecimalFormat.format(sum_distance));

                mCurrentSpeed = bdLocation.getSpeed();
                if (mCurrentSpeed > mMaxSpeed) {
                    mMaxSpeed = mCurrentSpeed;
                }
                mCurrentSpeedText.setText(mDecimalFormat.format(mCurrentSpeed));
                mMaxSpeedText.setText(mDecimalFormat.format(mMaxSpeed));
            }
        }

        private LatLng fixOffset(double latitude, double longitude) {
            double z = Math.sqrt(latitude * latitude + longitude * longitude) + 0.00002 * Math.sin(longitude * Math.PI);
            double temp = Math.atan2(longitude, latitude) + 0.000003 * Math.cos(latitude * Math.PI);
            double bdLon = z * Math.cos(temp) + 0.0065;
            double bdLat = z * Math.sin(temp) + 0.006;
            return new LatLng(bdLat, bdLon);
        }

    };

    private Timer mTimer;
    private TimerTask mTimerTask;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 200) {
                Log.e(TAG, "receive message");
                pointstwo.add(p1);
                pointstwo.add(p2);
                OverlayOptions dotOptions = new DotOptions().center(p2).radius(6).color(0xAAFF0000);
                mBaiduMap.addOverlay(dotOptions);
                OverlayOptions polyOptions = new PolylineOptions().width(4).color(0xAAFF0000).points(pointstwo);
                mBaiduMap.addOverlay(polyOptions);
                p1 = p2;
                mLocationClient.requestLocation();
            }
        }
    };

    private RelativeLayout mMapViewContainer;
    private Button mLocationButton, mControllerButton;
    private TextView mCurrentSpeedText, mMaxSpeedText;
    private TextView mDistanceText;
    private Chronometer mChronometer;

    private static final int PERMISSION_REQUEST_CODE = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView(savedInstanceState);
        getPermission();
    }

    private void initView(Bundle savedInstanceState) {
        mMapViewContainer = (RelativeLayout) findViewById(R.id.id_map_container);
        mLocationButton = (Button) findViewById(R.id.id_start_button);
        mLocationButton.setOnClickListener(this);
        mControllerButton = (Button) findViewById(R.id.id_stop_button);
        mControllerButton.setOnClickListener(this);
        mCurrentSpeedText = (TextView) findViewById(R.id.id_current_speed_text);
        mMaxSpeedText = (TextView) findViewById(R.id.id_max_speed_text);
        mDistanceText = (TextView) findViewById(R.id.id_distance_text);
        mChronometer = (Chronometer) findViewById(R.id.id_chronometer);
        initMap(savedInstanceState);
    }

    private void getPermission() {
        int hasLocationPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission_group.LOCATION);
        int hasStoragePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission_group.STORAGE);
        if (hasLocationPermission != PackageManager.PERMISSION_GRANTED ||
                hasStoragePermission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS,
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS
            }, PERMISSION_REQUEST_CODE);
        } else {
            initLocation();
        }
    }

    private void initMap(Bundle savedInstanceState) {
        mMapView = (MapView) findViewById(R.id.bmapView);
        mMapView.onCreate(this, savedInstanceState);
        mBaiduMap = mMapView.getMap();
        mBaiduMap.setMyLocationEnabled(true);
        BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.mipmap.ic_dot);
        mBaiduMap.setMyLocationConfigeration(new MyLocationConfiguration(MyLocationConfiguration.LocationMode.FOLLOWING, true, descriptor));
    }

    private void initLocation() {
        mLocationClient = new LocationClient(getApplicationContext());
        LocationClientOption option = new LocationClientOption();
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        option.setCoorType("bd09ll"); //可选，默认gcj02，设置返回的定位结果坐标系
        option.setScanSpan(3000); //可选，默认0，即仅定位一次，设置发起定位请求的间隔需要大于等于1000ms才是有效的
        option.setIsNeedAddress(false); //可选，设置是否需要地址信息，默认不需要
        option.setOpenGps(true); //可选，默认false,设置是否使用gps
        option.setLocationNotify(false); //可选，默认false，设置是否当GPS有效时按照1S/1次频率输出GPS结果
        option.setIsNeedLocationDescribe(false); //可选，默认false，设置是否需要位置语义化结果，可以在BDLocation.getLocationDescribe里得到，结果类似于“在北京天安门附近”
        option.setIsNeedLocationPoiList(false); //可选，默认false，设置是否需要POI结果，可以在BDLocation.getPoiList里得到
        option.setIgnoreKillProcess(false); //可选，默认true，定位SDK内部是一个SERVICE，并放到了独立进程，设置是否在stop的时候杀死这个进程，默认不杀死
        option.SetIgnoreCacheException(false); //可选，默认false，设置是否收集CRASH信息，默认收集
        option.setEnableSimulateGps(false); //可选，默认false，设置是否需要过滤GPS仿真结果，默认需要
        mLocationClient.setLocOption(option);
        mLocationClient.registerLocationListener(mBDLocationListener);
        mLocationClient.start();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                initLocation();
            } else {
                Toast.makeText(MainAppActivity.this, "未授权", Toast.LENGTH_LONG).show();
            }
        }
    }

    private void startTask() {
        if (mTimer == null) {
            mTimer = new Timer();
        }
        if (mTimerTask == null) {
            mTimerTask = new TimerTask() {
                @Override
                public void run() {
                    mHandler.sendEmptyMessage(200);
                }
            };
        }
        if (mTimer != null) {
            try {
                mBaiduMap.clear();
                pointstwo.clear();
                sum_distance = 0;
                mMaxSpeed = 0;
                mCurrentSpeed = 0;
                mTimer.schedule(mTimerTask, 1000, 1000);
                mChronometer.setBase(SystemClock.elapsedRealtime());
                mChronometer.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void stopTask() {
        if (mTimer != null) {
            mTimer.cancel();
            mTimer = null;
        }
        if (mTimerTask != null) {
            mTimerTask.cancel();
            mTimerTask = null;
        }
        mChronometer.stop();
    }

    /**
     * 计算距离
     */
    private double gps2m(double lat_a, double lng_a, double lat_b, double lng_b) {
        double radLat1 = (lat_a * Math.PI / 180.0);
        double radLat2 = (lat_b * Math.PI / 180.0);
        double a = radLat1 - radLat2;
        double b = (lng_a - lng_b) * Math.PI / 180.0;
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        //s = Math.round(s * 10000) / 10000;
        return 1.38 * s;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.id_stop_button:
                if (!mStart) {
                    return;
                }
                mLocationClient.stop();
                stopTask();
                mStart = false;
                addEndMarker();
                save();
                share();
                break;
            case R.id.id_start_button:
                if (mStart) {
                    return;
                }
//                mLocationClient.requestLocation();
//                SystemClock.sleep(50);
                mLocationClient.start();
                startTask();
                mStart = true;
                addStartMarker();
                break;
        }
    }

    private void save() {
        History history = new History();
        history.setDistance(Double.valueOf(mDistanceText.getText().toString()));
        history.setTime(mChronometer.getText().toString());
        HistoryDao.add(this, history);
    }

    private void share() {
        final View view = LayoutInflater.from(this).inflate(R.layout.layout_share, new LinearLayout(this), false);
        ImageView image = (ImageView) view.findViewById(R.id.id_snapshot_view);
        TextView distance = (TextView) view.findViewById(R.id.id_distance_text);
        TextView time = (TextView) view.findViewById(R.id.id_consume_time);
        // final Bitmap snapshot = BitmapUtils.getViewBitmap(mMapViewContainer);
        // image.setImageBitmap(snapshot);
        double dis = Double.valueOf(mDistanceText.getText().toString());
        Log.i("MainApp", "dis = " + dis);
        if (dis >= 1000.0) {
            dis /= 1000.0;
            distance.setText("路程：" + mDecimalFormat.format(dis) + "km");
        } else {
            distance.setText("路程：" + dis + "m");
        }
        time.setText("耗时：" + mChronometer.getText().toString());
        SystemClock.sleep(50);
        mBaiduMap.snapshot(new SnapshotCallback(image));
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                showDialog(view);
            }
        }, 400);
    }

    private class SnapshotCallback implements BaiduMap.SnapshotReadyCallback {

        private ImageView imageView;

        SnapshotCallback(ImageView imageView) {
            this.imageView = imageView;
        }

        @Override
        public void onSnapshotReady(Bitmap bitmap) {
            imageView.setImageBitmap(bitmap);
        }
    }

    private void showDialog(final View view) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setView(view);
        builder.setPositiveButton("分享", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                final Bitmap share = BitmapUtils.getViewBitmap(view);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.getDefault());
                String tmp = "snapshot_" + sdf.format(new Date()) + ".jpg";
                File file = FileUtils.convertBitmapToFile(share, tmp);
                if (file == null) {
                    Toast.makeText(MainAppActivity.this, "unknown error", Toast.LENGTH_SHORT).show();
                    return;
                }
                Uri uri = Uri.fromFile(file);
                Intent intent = new Intent(Intent.ACTION_SEND);
                intent.setType("image/*");
                intent.putExtra(Intent.EXTRA_SUBJECT, "分享");
                intent.putExtra(Intent.EXTRA_STREAM, uri);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(Intent.createChooser(intent, getTitle()));
            }
        });
        builder.setNegativeButton("完成", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.show();
    }

    private void addStartMarker() {
        BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.mipmap.ic_start);
        OverlayOptions option = new MarkerOptions().position(p1).icon(bitmap);
        mBaiduMap.addOverlay(option);
    }

    private void addEndMarker() {
        BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.mipmap.ic_end);
        OverlayOptions option = new MarkerOptions().position(p1).icon(bitmap);
        mBaiduMap.addOverlay(option);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mMapView.onSaveInstanceState(outState);
    }

    @Override
    protected void onDestroy() {
        mLocationClient.stop();
        mBaiduMap.setBaiduHeatMapEnabled(false);
        mMapView.onDestroy();
        mBaiduMap.clear();
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_history) {
            startActivity(new Intent(MainAppActivity.this, HistoryActivity.class));
        }
        return true;
    }
}
